public class Case
{
    private static final short DEFAULT=1;
    private static final int UNKNOW=-1;
    private static final int UNWALKABLE=-1;

    int x;
    int y;

    boolean Walkable;  //Peut-on passer à travers ?  
    boolean isClosed;  //Suis-je dans la openList ?
    boolean isOpen;    //Suis-je dans la closedList ?
    short typeTerrain; //Indique le temps nécessaire pour traverser cette case. 
                       //1 : valeur par défault;
    int Fcost;
    int Gcost;
    int Hcost;
    
    Case father;       //Va servir à tracer le chemin après application du pathFiding

    /*Path Scoring

      The key to determining which squares to use when figuring out the path is the following equation:

      F= G + H 

      * G = the movement cost to move from the starting point A 
      to a given square on the grid, following the path generated to get there. 

      * H = the estimated movement cost to move from that given square on the grid 
      to the final destination, point B. */

    //Case par défaut.
    public Case(int x, int y)
    {
	this.x=x;
	this.y=y;
	
	this.Walkable=true;
	this.isClosed=false;
	this.isOpen=false;
	this.typeTerrain=DEFAULT;

	this.Fcost=UNKNOW;
	this.Gcost=UNKNOW;
	this.Hcost=UNKNOW;

	this.father=null;
    }

    //Case avec un type de terrain plus difficile à traverser.
    public Case(int x, int y, short typeTerrain)
    {
	this(x,y);
	if(typeTerrain!=UNWALKABLE)
	    this.typeTerrain=typeTerrain;
	else
	    this.Walkable=false;
    }

    /* Voici le contexte ou l'on va appeler ces deux fonctions :
       Nous sommes sur une case, et sur toutes les cases voisines, nous allons calculer les F G et H*/

    public void setALLcost(Case prochaineCase, int xGoal, int yGoal)
    {

	setHcost( prochaineCase, xGoal, yGoal);
       	setGcost( prochaineCase, xGoal, yGoal);
	prochaineCase.Fcost=prochaineCase.Gcost +prochaineCase.Hcost;
    }

    //On calcule sur "prochaineCase" le cout approximatif du chemin restant.
    public void setHcost(Case prochaineCase, int xGoal, int yGoal)
    {
    	prochaineCase.Hcost= Math.abs(prochaineCase.x-xGoal)+Math.abs(prochaineCase.y-yGoal);
    }

    //Il s'agit du "cout" pour aller de this ( case courante) à la prochaine case.
    public void setGcost(Case prochaineCase, int xGoal, int yGoal)
    {
	int diffX=Math.abs(this.x-prochaineCase.x);
	int diffY=Math.abs(this.y-prochaineCase.y);
	prochaineCase.Gcost=((diffX+diffY==1)?10:14)+this.typeTerrain+this.Fcost;
    }
   
    

    public void afficherCase(boolean coord,
			     boolean walkable,
			     boolean isClosed,
			     boolean isOpen,
			     boolean terrain,
			     boolean f, 
			     boolean g ,
			     boolean h,
			     boolean father)
    {
	if(coord)
	    System.out.print("("+x+", "+y+") ");

	if(walkable)
	    System.out.print((Walkable?"  ":"X "));

	if(isOpen) 
	    System.out.print((this.isOpen?"Op ":"   "));

	if(isClosed)
	    System.out.print((this.isClosed?"Cl ":"   "));

	if(terrain)
	    System.out.print(this.typeTerrain+" ");

	if(f) 
	    System.out.print((this.Fcost!=-1?("F :"+this.Fcost):"     ")+" ");


	if(g )
	    System.out.print((this.Gcost!=-1?("G :"+this.Gcost):"     ")+" ");

	if(h)
	    System.out.print((this.Hcost!=-1?("H :"+this.Hcost):"    ")+" ");

	if(father)
	    if(this.father==null)
		System.out.print("              ");
	    else
		System.out.print("père : ("+this.father.x+", "+this.father.y+") ");
    
    }
}